/****************************************************************
* @file   : test.cpp
* @author : NingJian (freegodly@gmail.com)
* @date   : 05/26/21 09:38:22
* @brief   :  验证测试算法
****************************************************************/

#include <iostream>
#include "eth_types.h"
#include "eth_func.hpp"
#include <memory>
#include "pcie_tools.hpp"
#include <chrono>

using namespace std;
using namespace eth;
using namespace eth::mcore;
using namespace std::chrono;
using timer = std::chrono::steady_clock;

int main()
{

// {
// "jsonrpc": "2.0", 
// "id": 0, 
// "result": [
//     "0x990a7b593e4a43f203636687d3b362ea4496bd0593cddb5f6ea62aac2326ec74", 
//     "0x3646e1f9abad7750d559c03326ae5841c98e2fff3ee4ef7e1bc354b4499c946d", 
//     "0x000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffff"
// ]
// }
    std::string sHeaderHash ="0x990a7b593e4a43f203636687d3b362ea4496bd0593cddb5f6ea62aac2326ec74";
    sHeaderHash = "0x3d36e0e4bf38e352bdde11dabd8beed9da63647b69fc6dcfbac3a8d53653da8f";
    std::string sSeedHash   ="0x3646e1f9abad7750d559c03326ae5841c98e2fff3ee4ef7e1bc354b4499c946d";
    std::string sShareTarget="0x000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffff";


   // test h256

   hash256 seed = hash256_from_string(sSeedHash);
   hash256 header = hash256_from_string(sHeaderHash);
   hash256 boundary = hash256_from_string(sShareTarget);

   cout << "seed : " << hash256_to_string(seed) << endl;
   cout << "header : " << hash256_to_string(header) << endl;
   cout << "boundary : " << hash256_to_string(boundary) << endl;

   int epoch = find_epoch_number(seed);

   std::cout << "epoch : " << epoch << endl;

    auto start_time = timer::now();
    std::shared_ptr<eth_context> context =  get_eth_context(epoch, true);
    auto current_duration = double(duration_cast<milliseconds>(timer::now() - start_time).count());
    std::cout << "get_eth_context init times:" << current_duration / 1000.0 << "s" << endl;

 
   std::cout << "lightSize : " << context->light_cache_num_items * 64 / 1024.0 / 1024.0  << "MB" << endl;
   std::cout << "dagSize : " << (size_t)context->full_dataset_num_items * 128 / 1024.0 / 1024.0/1024.0 << "GB"  << endl;

    std::cout << "full_dataset_num_items : " << context->full_dataset_num_items << endl;

   if(context->full_dataset)
   {
    cout << "full_dataset[0] : " << hash1024_to_string(context->full_dataset[0]) << endl;
    cout << "full_dataset[1] : " << hash1024_to_string(context->full_dataset[1]) << endl;
    cout << "full_dataset[2] : " << hash1024_to_string(context->full_dataset[2]) << endl;
   }
   

   ////////////////////////////// for PCIE(virtual)
   pcie_initDevice();
   pcie_initEpoch_internal(context);

   pcie_set_header(header);

   uint64_t upper64OfBoundary;
   memcpy(&upper64OfBoundary, boundary.bytes, 8);
   upper64OfBoundary = __bswap_constant_64(upper64OfBoundary);
   std::cout << "upper64OfBoundary ： " <<  upper64OfBoundary << endl;
   pcie_set_target(upper64OfBoundary);
   pcie_debug();



   uint64_t start_nonce = 0xd1e631d90c618400;
   size_t iterations = 0x100; 

   search_results sr;
   pcie_ethash_search(sr,start_nonce,  iterations);


    if(sr.isfound){
        std::cout << "nonce = " << sr.nonce << " result_hash = " << hash256_to_string(sr.result_hash)<< " header_hash = " << hash256_to_string(sr.header_hash) << endl;
    } else {
        std::cout << " not found!" << std::endl;
    }  

    return 0;
}